#include "QQChatView.h"

QQChatView::QQChatView(QWidget* parent)
	: ElaScrollPage(parent)
{
	this->setAcceptDrops(true);
	this->setMouseTracking(true);

	mPictureToFileDialog = new QQContentDialog(parent);
	mPictureToFileDialog->setFixedHeight(150);
	ElaText* pictureToFileDialogTitle = new ElaText(mPictureToFileDialog);
	pictureToFileDialogTitle->setText(tr("This picture is too large,need you send this by file?"));
	pictureToFileDialogTitle->setAlignment(Qt::AlignCenter);
	pictureToFileDialogTitle->setTextPointSize(15);
	pictureToFileDialogTitle->setTextPixelSize(15);
	pictureToFileDialogTitle->setWordWrap(true);
	mPictureToFileDialog->setCentralWidget(pictureToFileDialogTitle);
	mPictureToFileDialog->setLeftButtonText(tr("Yes"));
	mPictureToFileDialog->setRightButtonText(tr("No"));
	mPictureToFileDialog->setMiddleButtonVisible(false);

	QLabel* indexNullptrLabel = new QLabel(this);
	indexNullptrLabel->setAlignment(Qt::AlignCenter);
	indexNullptrLabel->setText(tr("There is no message at this time!"));

	mIndexs = new ElaListView(this);
	mIndexs->setSelectionMode(QAbstractItemView::SingleSelection);
	mIndexs->setSelectionBehavior(QAbstractItemView::SelectRows);
	mIndexs->setEditTriggers(QAbstractItemView::NoEditTriggers);
	mIndexsModel = new QStandardItemModel(this);
	mIndexs->setModel(mIndexsModel);
	mIndexsDelegate = new QQChatIndexDelegate(this);
	mIndexs->setItemDelegate(mIndexsDelegate);
	mIndexs->setItemHeight(80);
	mIndexs->setUniformItemSizes(true);

	QStackedLayout* indexStackedLayout = new QStackedLayout;
	indexStackedLayout->addWidget(indexNullptrLabel);
	indexStackedLayout->addWidget(mIndexs);

	QLabel* messageNullptrLabel = new QLabel(this);
	messageNullptrLabel->setAlignment(Qt::AlignCenter);
	QString image = qq_settings->applicationImageLibraryDirectory() + "QQ_White.png";
	messageNullptrLabel->setPixmap(QPixmap(image));

	mMessages = new ElaListView(this);
	mMessages->setSelectionMode(QAbstractItemView::NoSelection);
	mMessages->setEditTriggers(QAbstractItemView::NoEditTriggers);
	mMessagesModel = new QQChatMessageModel(this);

	/*for (int i = 0; i < 10; ++i)
	{
		mMessagesModel->addFileMessage(i, QQMessageSenderType::Self, "fuck you", ":/QQClient/QQ.png",
			"C:/Users/30842/Desktop/IMQQ/client/Resource/QQ.png");
	}

	for (int i = 0; i < 10; ++i)
	{
		mMessagesModel->addTextMessage(i, QQMessageSenderType::Self, "fuck you", ":/QQClient/QQ.png",
			":/QQClient/QQ.png");
	}

	for (int i = 0; i < 10; ++i)
	{
		mMessagesModel->addImageMessage(i, QQMessageSenderType::Self, "fuck you", ":/QQClient/QQ.png",
			":/QQClient/QQ.png");
	}*/



	mMessages->setModel(mMessagesModel);
	mMessagesDelegate = new QQChatMessageDelegate(mMessages);
	mMessages->setItemDelegate(mMessagesDelegate);
	mMessages->setIsTransparent(true);

	mDragMessageMask = new QQMaskWidget(mMessages);
	mDragMessageMask->move(0, 0);
	mDragMessageMask->setVisible(false);
	QLabel* dragMessageIcon = new QLabel(mDragMessageMask);
	dragMessageIcon->setAlignment(Qt::AlignCenter);
	dragMessageIcon->setPixmap(ElaIcon::getInstance()->getElaIcon(ElaIconType::Folder).pixmap(64, 64));
	ElaText* dragMessageText = new ElaText(mDragMessageMask);
	dragMessageText->setText(tr("Send this by file"));
	dragMessageText->setAlignment(Qt::AlignCenter);
	dragMessageText->setTextPixelSize(10);
	dragMessageText->setTextPointSize(10);
	QVBoxLayout* dragMessageLayout = new QVBoxLayout(mDragMessageMask);
	dragMessageLayout->setContentsMargins(0, 0, 0, 0);
	dragMessageLayout->setSpacing(0);
	dragMessageLayout->addStretch();
	dragMessageLayout->addWidget(dragMessageIcon);
	dragMessageLayout->addWidget(dragMessageText);
	dragMessageLayout->addStretch();

	mToolBar = new ElaToolBar(this);
	mToolBar->addElaIconAction(ElaIconType::FaceSmile, tr("emtion"));
	mToolBar->addElaIconAction(ElaIconType::Image, tr("picture"));
	mToolBar->addElaIconAction(ElaIconType::Folder, tr("file"));
	mEmojiView = new QQEmojiView(this);
	mFileView = new QQFileView(parent);

	mRealCommunicateToolBar = new ElaToolBar(this);
	mRealCommunicateToolBar->addElaIconAction(ElaIconType::AudioDescription, tr("audio"));
	mRealCommunicateToolBar->addElaIconAction(ElaIconType::Camera, tr("video"));
	mAudioView = new QQAudioView(this);
	mVideoView = new QQVideoView(this);

	QHBoxLayout* messageToolLayout = new QHBoxLayout;
	messageToolLayout->setContentsMargins(0, 0, 0, 0);
	messageToolLayout->setSpacing(0);
	messageToolLayout->addWidget(mToolBar);
	messageToolLayout->addStretch();
	messageToolLayout->addWidget(mRealCommunicateToolBar);

	mMessageInput = new QQTextEdit(this);
	mMessageInput->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	mMessageInput->setAcceptDrops(false);
	mMessageSend = new ElaPushButton(this);
	mMessageSend->setText(tr("Send"));
	mMessageSend->setMinimumWidth(150);
	mMessageClear = new ElaPushButton(this);
	mMessageClear->setText(tr("Clear"));
	mMessageClear->setMinimumWidth(150);

	QHBoxLayout* messageButtonLayout = new QHBoxLayout;
	messageButtonLayout->setAlignment(Qt::AlignRight);
	messageButtonLayout->addWidget(mMessageSend);
	messageButtonLayout->addWidget(mMessageClear);
	messageButtonLayout->setSpacing(5);

	QWidget* messageInputWidget = new QWidget(this);
	QVBoxLayout* messageInputLayout = new QVBoxLayout(messageInputWidget);
	messageInputLayout->setContentsMargins(0, 0, 0, 0);
	messageInputLayout->setSpacing(0);
	messageInputLayout->addLayout(messageToolLayout);
	messageInputLayout->addWidget(mMessageInput);
	messageInputLayout->addLayout(messageButtonLayout);
	messageInputLayout->setStretch(0, 1);
	messageInputLayout->setStretch(1, 2);
	messageInputLayout->setStretch(2, 1);

	mDragMessageInputMask = new QQMaskWidget(messageInputWidget);
	mDragMessageInputMask->move(0, 0);
	mDragMessageInputMask->setVisible(false);
	QLabel* dragInputIcon = new QLabel(mDragMessageInputMask);
	dragInputIcon->setAlignment(Qt::AlignCenter);
	dragInputIcon->setPixmap(ElaIcon::getInstance()->getElaIcon(ElaIconType::Image).pixmap(64, 64));
	ElaText* dragInputText = new ElaText(mDragMessageInputMask);
	dragInputText->setText(tr("Send this by picture"));
	dragInputText->setAlignment(Qt::AlignCenter);
	dragInputText->setTextPixelSize(10);
	dragInputText->setTextPointSize(10);
	QVBoxLayout* dragMessageInputLayout = new QVBoxLayout(mDragMessageInputMask);
	dragMessageInputLayout->setContentsMargins(0, 0, 0, 0);
	dragMessageInputLayout->setSpacing(0);
	dragMessageInputLayout->addStretch();
	dragMessageInputLayout->addWidget(dragInputIcon);
	dragMessageInputLayout->addWidget(dragInputText);
	dragMessageInputLayout->addStretch();

	QVBoxLayout* messageLayout = new QVBoxLayout;
	messageLayout->setContentsMargins(0, 0, 0, 0);
	messageLayout->setSpacing(0);
	messageLayout->addWidget(mMessages);
	messageLayout->addWidget(messageInputWidget);
	messageLayout->setStretch(0, 6);
	messageLayout->setStretch(1, 4);

	QStackedLayout* messageLayoutStackedLayout = new QStackedLayout;
	messageLayoutStackedLayout->addWidget(messageNullptrLabel);
	QWidget* messageWidget = new QWidget(this);
	messageWidget->setLayout(messageLayout);
	messageLayoutStackedLayout->addWidget(messageWidget);
	messageLayoutStackedLayout->setCurrentIndex(1);

	QWidget* chat = new QWidget(this);
	QHBoxLayout* layout = new QHBoxLayout(chat);
	layout->addLayout(indexStackedLayout);
	layout->addLayout(messageLayoutStackedLayout);
	layout->setContentsMargins(0, 0, 0, 0);
	layout->setSpacing(0);
	layout->setStretch(0, 1);
	layout->setStretch(1, 3);

	this->addCentralWidget(chat);
	this->setTitleVisible(false);

	connect(mPictureToFileDialog, &QQContentDialog::leftButtonClicked, mPictureToFileDialog, &QQContentDialog::accept);
	connect(mPictureToFileDialog, &QQContentDialog::rightButtonClicked, mPictureToFileDialog, &QQContentDialog::reject);
	connect(mIndexs, &ElaListView::clicked, this, &QQChatView::doIndexClicked);
	connect(mToolBar, &ElaToolBar::actionTriggered, this, &QQChatView::doToolBarClicked);
	connect(mEmojiView, &QQEmojiView::sendEmoji, this, &QQChatView::doLoadEmojiToInput);
	connect(mRealCommunicateToolBar, &ElaToolBar::actionTriggered, this, &QQChatView::doRealCommunicateToolBarClicked);
	connect(mAudioView, &QQAudioView::microphone, this, &QQChatView::changeAudioMicrophoneState);
	connect(mAudioView, &QQAudioView::accept, this, &QQChatView::acceptRealCommunicateAudioByMe);
	connect(mAudioView, &QQAudioView::refuse, this, &QQChatView::refuseRealCommunicateAudioByMe);
	connect(mVideoView, &QQVideoView::microphone, this, &QQChatView::changeVideoMicrophoneState);
	connect(mVideoView, &QQVideoView::camera, this, &QQChatView::changeVideoCameraState);
	connect(mVideoView, &QQVideoView::accept, this, &QQChatView::acceptRealCommunicateVideoByMe);
	connect(mVideoView, &QQVideoView::refuse, this, &QQChatView::refuseRealCommunicateVideoByMe);
	connect(mMessageSend, &ElaPushButton::clicked, this, &QQChatView::doSendMessageClicked);
	connect(mMessageClear, &ElaPushButton::clicked, mMessageInput, &QQTextEdit::clear);
}

QQChatView::~QQChatView()
{
}

void QQChatView::showMessageBar(const QString& message)
{
	ElaMessageBar::warning(ElaMessageBarType::PositionPolicy::Top, QString(""), message, 2000, this);
}

void QQChatView::loadIndex(const QQChatIndexItem& index)
{
	QStandardItem* item = new QStandardItem;
	item->setData(index.account, Qt::UserRole + 0);
	item->setData(index.icon, Qt::UserRole + 1);
	item->setData(index.nickname, Qt::UserRole + 2);
	item->setData(index.keyPoints, Qt::UserRole + 3);
	mIndexsModel->appendRow(item);
}

void QQChatView::loadIndexs(const QList<QQChatIndexItem>& indexs)
{
	int size = indexs.size();
	mIndexsModel->insertRows(0, size);
	for (int i = 0; i < size; ++i)
	{
		QStandardItem* item = new QStandardItem;
		item->setData(indexs[i].account, Qt::UserRole + 0);
		item->setData(indexs[i].icon, Qt::UserRole + 1);
		item->setData(indexs[i].nickname, Qt::UserRole + 2);
		item->setData(indexs[i].keyPoints, Qt::UserRole + 3);
		mIndexsModel->setItem(i, item);
	}
}

void QQChatView::loadMessageOnView(const QQMessageItem& message)
{
	QModelIndex index = mIndexs->currentIndex();
	QString user = index.data(Qt::UserRole + 0).toString();
	if (message.sender == user || message.receiver == user)
	{
		/*QStandardItem* item = new QStandardItem;
		int type = qq_settings->getUserInfo()->account == message.sender ? 0 : 1;
		item->setData(type, Qt::UserRole + 0);
		item->setData(message.icon, Qt::UserRole + 1);
		item->setData(message.nickname, Qt::UserRole + 2);
		item->setData(message.content, Qt::UserRole + 3);
		mMessagesModel->appendRow(item);
		mMessages->scrollToBottom();*/
	}
	else
	{
		QStandardItem* item = mIndexsModel->itemFromIndex(index);
		int keyPoints = item->data(Qt::UserRole + 3).toInt() + 1;
		item->setData(Qt::UserRole + 3, keyPoints);
	}
}

void QQChatView::loadMessagesOnView(const QList<QQMessageItem>& messages)
{
	int size = messages.size();
	mMessagesModel->insertRows(0, size);
	for (int i = 0; i < size; ++i)
	{
		/*QStandardItem* item = new QStandardItem;
		int type = qq_settings->getUserInfo()->account == messages[i].sender ? 0 : 1;
		item->setData(type, Qt::UserRole + 0);
		item->setData(messages[i].icon, Qt::UserRole + 1);
		item->setData(messages[i].nickname, Qt::UserRole + 2);
		item->setData(messages[i].content, Qt::UserRole + 3);
		mMessagesModel->setItem(i, item);*/
	}
	mMessages->scrollToBottom();
}

void QQChatView::loadEmojiDataOnView(const QList<QQChatEmoji>& emojis)
{
	if (!mEmojiView || mEmojiView->isVisible())
		return;
	mEmojiView->appendEmojiTable(emojis);
	QPoint pos = mToolBar->mapToGlobal(QPoint(0, 0));
	pos.setX(pos.x() + 5);
	pos.setY(pos.y() - mEmojiView->maximumSize().height());
	mEmojiView->move(pos);
	mEmojiView->show();
	mEmojiView->setHaveLoaded(true);
}

void QQChatView::loadPictureInInput(const QStringList& filenames)
{
	for (int i = 0; i < filenames.size(); i++)
	{
		QTextCursor cursor = mMessageInput->textCursor();
		QString type = QQSystemApi::getFileMimeType(filenames[i]).name();
		if (type == "image/gif")
		{
			QTextImageFormat format;
			QPixmap pixmap(filenames[i]);
			pixmap = pixmap.scaled(qq_settings->getPictureScreenMaxSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
			format.setWidth(pixmap.width());
			format.setHeight(pixmap.height());
			format.setVerticalAlignment(QTextCharFormat::AlignBaseline);
			mMessageInput->addAnimation(filenames[i], format);
		}
		else
		{
			QTextImageFormat format;
			QPixmap pixmap(filenames[i]);
			pixmap = pixmap.scaled(qq_settings->getPictureScreenMaxSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
			format.setWidth(pixmap.width());
			format.setHeight(pixmap.height());
			format.setVerticalAlignment(QTextCharFormat::AlignBaseline);
			format.setName(filenames[i]);
			cursor.insertImage(format);
		}
	}
}

int QQChatView::openPictureToFileDialog()
{
	if (!mPictureToFileDialog || mPictureToFileDialog->isVisible())
		return QDialog::Rejected;
	return mPictureToFileDialog->exec();
}

int QQChatView::openFileSendDialog(const QFileInfoList& fileinfos)
{
	if (!mFileView || mFileView->isVisible())
		return QDialog::Rejected;
	mFileView->loadFiles(fileinfos);
	return mFileView->exec();
}

void QQChatView::openAudioView(int detail, const QString& account, const QString& nickname, QPixmap pixmap)
{
	if (!mAudioView || mAudioView->isVisible())
		return;
	else if (mVideoView && mVideoView->isVisible())
		return;
	mAudioView->setTargetUserInfo(account, nickname, pixmap);
	if (detail == 0)
		mAudioView->openThisInSender();
	else
		mAudioView->openThisInReceiver();
}

void QQChatView::startRealCommunicateAudio()
{
	if (mAudioView && mAudioView->isVisible())
		mAudioView->startRealCommunicateAudio();
}

void QQChatView::stopRealCommunicateAudio(QQAudioView::StopType type)
{
	if (mAudioView && mAudioView->isVisible())
		mAudioView->stopRealCommunicateAudio(type);
}

void QQChatView::openVideoView(int detail, const QString& account, const QString& nickname, QPixmap pixmap)
{
	if (!mVideoView || mVideoView->isVisible())
		return;
	else if (mAudioView && mAudioView->isVisible())
		return;
	mVideoView->setTargetUserInfo(account, nickname, pixmap);
	if (detail == 0)
		mVideoView->openThisInSender();
	else
		mVideoView->openThisInReceiver();
}

QPair<QWidget*, QWidget*> QQChatView::startRealCommunicateVideo()
{
	if (mVideoView && mVideoView->isVisible())
		return mVideoView->startRealCommunicateVideo();
	return {};
}

void QQChatView::stopRealCommunicateVideo(QQVideoView::StopType type)
{
	if (mVideoView && mVideoView->isVisible())
		mVideoView->stopRealCommunicateVideo(type);
}

void QQChatView::setVideoBackground(const QPixmap& pixmap)
{
	if (mVideoView && mVideoView->isVisible())
		mVideoView->setBackground(pixmap);
}

void QQChatView::doMousePress(QPoint pos, Qt::MouseButton type)
{
	if (mEmojiView && mEmojiView->isVisible())
	{
		QPoint widget_pos = mEmojiView->mapToGlobal(QPoint(0, 0));
		QRect widget_rect = mEmojiView->rect();
		QRect rect(widget_pos, widget_rect.size());
		if (!rect.contains(pos))
		{
			mEmojiView->hide();
		}
	}
}

void QQChatView::doUpdateFileProgress(const QString& filename, int progress)
{
}

void QQChatView::dragEnterEvent(QDragEnterEvent* event)
{
	mDragMessageMask->setFixedSize(mDragMessageMask->parentWidget()->size());
	mDragMessageInputMask->setFixedSize(mDragMessageInputMask->parentWidget()->size());
	const QMimeData* mimeData = event->mimeData();
	if (mimeData->hasUrls())
	{
		QList<QUrl> urls = mimeData->urls();
		mIsDragAllPicture = true;
		for (int i = 0; i < urls.size(); i++)
		{
			QString path = urls[i].toLocalFile();
			QString type = QQSystemApi::getFileMimeType(path).name();
			if (type != "image/gif" && type != "image/png" && type != "image/jpeg" && type != "image/bmp")
			{
				mIsDragAllPicture = false;
				break;
			}
		}
	}
	event->accept();
	return ElaScrollPage::dragEnterEvent(event);
}

void QQChatView::dragMoveEvent(QDragMoveEvent* event)
{
	if (mIsDragAllPicture)
	{
		QPoint pos = this->mapToGlobal(event->pos());
		if (QQSystemApi::posInWidget(mDragMessageMask, pos))
		{
			mDragMessageMask->setVisible(true);
			mDragMessageMask->setMaskAlpha(10);
			mDragMessageInputMask->setVisible(true);
			mDragMessageInputMask->setMaskAlpha(0);
		}
		else if (QQSystemApi::posInWidget(mDragMessageInputMask, pos))
		{
			mDragMessageMask->setVisible(true);
			mDragMessageMask->setMaskAlpha(0);
			mDragMessageInputMask->setVisible(true);
			mDragMessageInputMask->setMaskAlpha(10);
		}
		else
		{
			mDragMessageMask->setVisible(false);
			mDragMessageMask->setMaskAlpha(0);
			mDragMessageInputMask->setVisible(false);
			mDragMessageInputMask->setMaskAlpha(0);
		}
	}
	return ElaScrollPage::dragMoveEvent(event);
}

void QQChatView::dropEvent(QDropEvent* event)
{
	if (mIsDragAllPicture)
	{
		if (mDragMessageMask && mDragMessageMask->isVisible())
			mDragMessageMask->hide();
		if (mDragMessageInputMask && mDragMessageInputMask->isVisible())
			mDragMessageInputMask->hide();
		QPoint pos = this->mapToGlobal(event->pos());
		if (QQSystemApi::posInWidget(mDragMessageMask, pos))
		{
			const QMimeData* mimeData = event->mimeData();
			QList<QUrl> urls = mimeData->urls();
			QFileInfoList files;
			for (int i = 0; i < urls.size(); i++)
				files.append(urls[i].toLocalFile());
			this->openFileSendDialog(files);
		}
		else if (QQSystemApi::posInWidget(mDragMessageInputMask, pos))
		{
			const QMimeData* mimeData = event->mimeData();
			QList<QUrl> urls = mimeData->urls();
			QStringList pixmaps;
			for (int i = 0; i < urls.size(); i++)
				pixmaps.append(urls[i].toLocalFile());
			this->loadPictureInInput(pixmaps);
		}
	}
	else
	{
		const QMimeData* mimeData = event->mimeData();
		QList<QUrl> urls = mimeData->urls();
		QFileInfoList files;
		for (int i = 0; i < urls.size(); i++)
			files.append(urls[i].toLocalFile());
		this->openFileSendDialog(files);
	}

	return ElaScrollPage::dropEvent(event);
}

void QQChatView::doIndexClicked(const QModelIndex& index)
{
	QString account = index.data(Qt::UserRole).toString();
	emit loadMessages(account);
}

void QQChatView::doToolBarClicked(QAction* action)
{
	QModelIndex index = mIndexs->currentIndex();
	QString user = index.data(Qt::UserRole + 0).toString();

	QList<QAction*> actions = mToolBar->actions();
	if (action == actions[0])
	{
		if (mEmojiView->getHaveLoaded())
		{
			QPoint pos = mToolBar->mapToGlobal(QPoint(0, 0));
			pos.setX(pos.x() + 5);
			pos.setY(pos.y() - mEmojiView->maximumSize().height());
			mEmojiView->move(pos);
			mEmojiView->show();
			return;
		}
		emit loadEmojiData(user);
	}
	else if (action == actions[1])
	{
		QStringList filenames =
			QFileDialog::getOpenFileNames(this,
				tr("Select picture"), QDir::rootPath(), "Image Files (*.png *.jpg *.bmp *.gif)");
		if (filenames.size() > 0)
			emit checkPicture(user, filenames);
	}
	else if (action == actions[2])
	{
		QStringList filenames = QFileDialog::getOpenFileNames(this,
			tr("Select file"), QDir::rootPath(), "All files (*.*)");
		if (filenames.size() > 0)
			emit checkFile(user, filenames);
	}
}

void QQChatView::doRealCommunicateToolBarClicked(QAction* action)
{
	QModelIndex index = mIndexs->currentIndex();
	QString user = index.data(Qt::UserRole + 0).toString();

	QList<QAction*> actions = mRealCommunicateToolBar->actions();
	if (action == actions[0])
	{
		emit sendRealCommunicateAudio(user);
	}
	else if (action == actions[1])
	{
		emit sendRealCommunicateVideo(user);
	}
}

void QQChatView::doLoadEmojiToInput(const QString& emoji, int type)
{
	mMessageInput->insertPlainText(emoji);
	mMessageInput->setFocus();
}

void QQChatView::doSendMessageClicked()
{
	QModelIndex index = mIndexs->currentIndex();
	QString user = index.data(Qt::UserRole + 0).toString();
	emit sendMessage(user, mMessageInput->toHtml());
	mMessageInput->clear();
}